package jmine.tec.performance.test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

import jmine.tec.utils.collection.SortedProperties;

/**
 * Classe que analise dados de performance de testes.
 * 
 * @author julien.renaut
 * @author joao.enomoto (refactor)
 */
public class PerformanceTestAnalyser {

    private List<DataCollector> dataCollectors;

    private AnalysisStatus status;

    /**
     * Constructor.
     * 
     * @param dataCollectors data collectors.
     */
    public PerformanceTestAnalyser(List<DataCollector> dataCollectors) {
        this.dataCollectors = dataCollectors;
        this.status = AnalysisStatus.IDLE;
    }

    /**
     * Inicializa a coleta de dados de performance.
     */
    public void startCollectingData(String name) {
        if (!this.status.isIdle()) {
            throw new IllegalStateException("Can't start data collecting if analyser is not idle");
        }
        this.status = AnalysisStatus.COLLECTING;
        for (DataCollector dataCollector : this.dataCollectors) {
            dataCollector.startCollect(name);
        }
    }

    /**
     * Finaliza a coleta de dados de performance.
     */
    public void stopCollectingData(String name) {
        if (!this.status.isCollecting()) {
            throw new IllegalStateException("Can't stop data collecting if analyser is not collecting data");
        }
        this.status = AnalysisStatus.IDLE;
        for (DataCollector dataCollector : this.dataCollectors) {
            dataCollector.stopCollect(name);
        }
    }

    /**
     * Escreve os dados de performance coletados.
     * 
     * @throws IOException exceção ao tentar escrever os dados de performance.
     */
    public void writeTimerData() throws IOException {
        if (!this.status.isIdle()) {
            throw new IllegalStateException("Can't write collected data if analyser is not idle");
        }
        Properties data = new SortedProperties();
        for (DataCollector dataCollector : this.dataCollectors) {
            data.putAll(dataCollector.getResultAsProperties());
        }
        for (Object metricName : data.keySet()) {
            Object metricResult = data.remove(metricName);
            data.put("root." + metricName, metricResult);
        }
        FileOutputStream fos = new FileOutputStream("target/performance.properties", false);
        data.store(fos, null);
        fos.close();
    }

    /**
     * @author joao.enomoto
     */
    private enum AnalysisStatus {
        IDLE, COLLECTING;

        /**
         * @return
         */
        public boolean isIdle() {
            return this.equals(IDLE);
        }

        /**
         * @return
         */
        public boolean isCollecting() {
            return this.equals(COLLECTING);
        }
    }
}